// Copyright (c) 2022 NetEase, Inc. All rights reserved.
// Use of this source code is governed by a MIT license that can be
// found in the LICENSE file.

package com.faceunity.nama.control;

import android.annotation.SuppressLint;
import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView;
import com.faceunity.core.utils.DecimalUtils;
import com.faceunity.nama.R;
import com.faceunity.nama.base.BaseDelegate;
import com.faceunity.nama.base.BaseListAdapter;
import com.faceunity.nama.base.BaseViewHolder;
import com.faceunity.nama.checkbox.CheckGroup;
import com.faceunity.nama.dialog.ToastHelper;
import com.faceunity.nama.entity.FaceBeautyBean;
import com.faceunity.nama.entity.FaceBeautyFilterBean;
import com.faceunity.nama.entity.ModelAttributeData;
import com.faceunity.nama.infe.AbstractFaceBeautyDataFactory;
import com.faceunity.nama.seekbar.DiscreteSeekBar;
import java.util.ArrayList;
import java.util.HashMap;

/** DESC： Created on 2021/4/26 */
public class FaceBeautyControlView extends BaseControlView {

  private AbstractFaceBeautyDataFactory mDataFactory;

  /*  美颜、美型 */
  private HashMap<String, ModelAttributeData> mModelAttributeRange;
  private ArrayList<FaceBeautyBean> mSkinBeauty;
  private ArrayList<FaceBeautyBean> mShapeBeauty;
  private int mSkinIndex = 0;
  private int mShapeIndex = 1;
  private BaseListAdapter<FaceBeautyBean> mBeautyAdapter;

  /* 滤镜 */
  private ArrayList<FaceBeautyFilterBean> mFilters;
  private BaseListAdapter<FaceBeautyFilterBean> mFiltersAdapter;

  private RecyclerView recyclerView;
  private DiscreteSeekBar discreteSeekBar;
  private CheckGroup checkGroup;
  private LinearLayout recoverLayout;
  private ImageView recoverImageView;
  private TextView recoverTextView;
  private View lineView;
  private LinearLayout bottomLayout;
  private ImageView imgBeautyCompared;

  private int currentTab = R.id.beauty_radio_skin_beauty;

  public FaceBeautyControlView(@NonNull Context context) {
    super(context);
    init();
  }

  public FaceBeautyControlView(@NonNull Context context, @Nullable AttributeSet attrs) {
    super(context, attrs);
    init();
  }

  public FaceBeautyControlView(
      @NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    init();
  }

  /**
   * 给控制绑定FaceBeautyController，数据工厂
   *
   * @param dataFactory IFaceBeautyDataFactory
   */
  public void bindDataFactory(AbstractFaceBeautyDataFactory dataFactory) {
    mDataFactory = dataFactory;
    mModelAttributeRange = dataFactory.getModelAttributeRange();
    mSkinBeauty = dataFactory.getSkinBeauty();
    mShapeBeauty = dataFactory.getShapeBeauty();
    mFilters = dataFactory.getBeautyFilters();
    mFiltersAdapter.setData(mFilters);
  }

  private void init() {
    LayoutInflater.from(mContext).inflate(R.layout.layout_face_beauty_control, this);
    initView();
    initAdapter();
    bindListener();
  }
  // region  init

  private void initView() {
    recyclerView = findViewById(R.id.recycler_view);
    discreteSeekBar = findViewById(R.id.seek_bar);
    checkGroup = findViewById(R.id.beauty_radio_group);
    recoverLayout = findViewById(R.id.lyt_beauty_recover);
    recoverImageView = findViewById(R.id.iv_beauty_recover);
    recoverTextView = findViewById(R.id.tv_beauty_recover);
    lineView = findViewById(R.id.iv_line);
    bottomLayout = findViewById(R.id.fyt_bottom_view);
    imgBeautyCompared = findViewById(R.id.img_beauty_compared);
    initHorizontalRecycleView(recyclerView);
  }

  /** 构造Adapter */
  private void initAdapter() {
    mFiltersAdapter =
        new BaseListAdapter<>(
            new ArrayList<>(),
            new BaseDelegate<FaceBeautyFilterBean>() {
              @Override
              public void convert(
                  int viewType, BaseViewHolder helper, FaceBeautyFilterBean data, int position) {
                helper.setText(R.id.tv_control, data.getDesRes());
                helper.setImageResource(R.id.iv_control, data.getImageRes());
                helper.itemView.setSelected(mDataFactory.getCurrentFilterIndex() == position);
              }

              @Override
              public void onItemClickListener(View view, FaceBeautyFilterBean data, int position) {
                if (mDataFactory.getCurrentFilterIndex() != position) {
                  changeAdapterSelected(
                      mFiltersAdapter, mDataFactory.getCurrentFilterIndex(), position);
                  mDataFactory.setCurrentFilterIndex(position);
                  mDataFactory.onFilterSelected(
                      data.getKey(), data.getIntensity(), data.getDesRes());
                  if (position == 0) {
                    discreteSeekBar.setVisibility(View.INVISIBLE);
                  } else {
                    seekToSeekBar(data.getIntensity(), 0.0, 1.0);
                  }
                }
              }
            },
            R.layout.list_item_control_title_image_square);

    mBeautyAdapter =
        new BaseListAdapter<>(
            new ArrayList<>(),
            new BaseDelegate<FaceBeautyBean>() {
              @Override
              public void convert(
                  int viewType, BaseViewHolder helper, FaceBeautyBean data, int position) {
                helper.setText(R.id.tv_control, data.getDesRes());
                double value = mDataFactory.getParamIntensity(data.getKey());
                double stand = mModelAttributeRange.get(data.getKey()).getStandV();
                if (DecimalUtils.doubleEquals(value, stand)) {
                  helper.setImageResource(R.id.iv_control, data.getCloseRes());
                } else {
                  helper.setImageResource(R.id.iv_control, data.getOpenRes());
                }
                boolean isShinSelected =
                    checkGroup.getCheckedCheckBoxId() == R.id.beauty_radio_skin_beauty;
                helper.itemView.setSelected(
                    isShinSelected ? mSkinIndex == position : mShapeIndex == position);

                if (!data.isCanUseFunction()) {
                  ImageView ivControl = helper.getView(R.id.iv_control);
                  ivControl.setImageAlpha(154);
                } else {
                  ImageView ivControl = helper.getView(R.id.iv_control);
                  ivControl.setImageAlpha(255);
                }
              }

              @Override
              public void onItemClickListener(View view, FaceBeautyBean data, int position) {
                boolean isShinSelected =
                    checkGroup.getCheckedCheckBoxId() == R.id.beauty_radio_skin_beauty;
                if ((isShinSelected && position == mSkinIndex)
                    || (!isShinSelected && position == mShapeIndex)) {
                  return;
                }
                if (!data.isCanUseFunction()) {
                  ToastHelper.showNormalToast(mContext, data.getToastRes());
                  return;
                }
                if (isShinSelected) {
                  changeAdapterSelected(mBeautyAdapter, mSkinIndex, position);
                  mSkinIndex = position;
                } else {
                  changeAdapterSelected(mBeautyAdapter, mShapeIndex, position);
                  mShapeIndex = position;
                }
                double value = mDataFactory.getParamIntensity(data.getKey());
                double stand = mModelAttributeRange.get(data.getKey()).getStandV();
                double maxRange = mModelAttributeRange.get(data.getKey()).getMaxRange();
                seekToSeekBar(value, stand, maxRange);
              }
            },
            R.layout.list_item_control_title_image_circle);
  }

  /** 绑定监听事件 */
  @SuppressLint("ClickableViewAccessibility")
  private void bindListener() {
    /*拦截触碰事件*/
    findViewById(R.id.fyt_bottom_view).setOnTouchListener((v, event) -> true);
    /*菜单控制*/
    bindBottomRadioListener();
    /*滑动条控制*/
    bindSeekBarListener();
    /*还原数据*/
    recoverLayout.setOnClickListener(
        (view) ->
            showDialog(
                mContext.getString(R.string.dialog_reset_avatar_model), () -> recoverData()));

    imgBeautyCompared.setOnTouchListener(
        (view, motionEvent) -> {
          int action = motionEvent.getAction();
          if (action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_MOVE) {
            view.setAlpha(0.75f);
            mDataFactory.enableFaceBeauty(false);
          } else if (action == MotionEvent.ACTION_UP) {
            view.setAlpha(1.0f);
            mDataFactory.enableFaceBeauty(true);
          }
          return true;
        });
  }

  /** 滚动条绑定事件 */
  private void bindSeekBarListener() {
    discreteSeekBar.setOnProgressChangeListener(
        new DiscreteSeekBar.OnSimpleProgressChangeListener() {
          @Override
          public void onProgressChanged(DiscreteSeekBar seekBar, int value, boolean fromUser) {
            if (!fromUser) {
              return;
            }
            double valueF = 1.0 * (value - seekBar.getMin()) / 100;
            if (checkGroup.getCheckedCheckBoxId() == R.id.beauty_radio_skin_beauty) {
              FaceBeautyBean bean = mSkinBeauty.get(mSkinIndex);
              double range = mModelAttributeRange.get(bean.getKey()).getMaxRange();
              double res = valueF * range;
              double intensity = mDataFactory.getParamIntensity(bean.getKey());
              if (!DecimalUtils.doubleEquals(res, intensity)) {
                mDataFactory.updateParamIntensity(bean.getKey(), res);
                setRecoverEnable(checkFaceSkinChanged());
                updateBeautyItemUI(mBeautyAdapter.getViewHolderByPosition(mSkinIndex), bean);
              }
            } else if (checkGroup.getCheckedCheckBoxId() == R.id.beauty_radio_face_shape) {
              FaceBeautyBean bean = mShapeBeauty.get(mShapeIndex);
              double range = mModelAttributeRange.get(bean.getKey()).getMaxRange();
              double res = valueF * range;
              double intensity = mDataFactory.getParamIntensity(bean.getKey());
              if (!DecimalUtils.doubleEquals(res, intensity)) {
                mDataFactory.updateParamIntensity(bean.getKey(), res);
                setRecoverEnable(checkFaceShapeChanged());
                updateBeautyItemUI(mBeautyAdapter.getViewHolderByPosition(mShapeIndex), bean);
              }
            } else if (checkGroup.getCheckedCheckBoxId() == R.id.beauty_radio_filter) {
              FaceBeautyFilterBean bean = mFilters.get(mDataFactory.getCurrentFilterIndex());
              if (!DecimalUtils.doubleEquals(bean.getIntensity(), valueF)) {
                bean.setIntensity(valueF);
                mDataFactory.updateFilterIntensity(valueF);
              }
            }
          }
        });
  }

  /** 底部导航栏绑定监听事件，处理RecycleView等相关布局变更 */
  private void bindBottomRadioListener() {
    checkGroup.setOnCheckedChangeListener(
        (group, checkedId) -> {
          currentTab = checkedId;
          if (checkedId == R.id.beauty_radio_skin_beauty
              || checkedId == R.id.beauty_radio_face_shape) {
            discreteSeekBar.setVisibility(View.VISIBLE);
            recoverLayout.setVisibility(View.VISIBLE);
            lineView.setVisibility(View.VISIBLE);
            imgBeautyCompared.setVisibility(View.VISIBLE);
          } else if (checkedId == R.id.beauty_radio_filter) {
            discreteSeekBar.setVisibility(
                (mDataFactory.getCurrentFilterIndex() == 0) ? View.INVISIBLE : View.VISIBLE);
            recoverLayout.setVisibility(View.GONE);
            lineView.setVisibility(View.GONE);
            imgBeautyCompared.setVisibility(View.VISIBLE);
          }
          if (checkedId == R.id.beauty_radio_skin_beauty) {
            mBeautyAdapter.setData(mSkinBeauty);
            recyclerView.setAdapter(mBeautyAdapter);
            FaceBeautyBean item = mSkinBeauty.get(mSkinIndex);
            double value = mDataFactory.getParamIntensity(item.getKey());
            double stand = mModelAttributeRange.get(item.getKey()).getStandV();
            double maxRange = mModelAttributeRange.get(item.getKey()).getMaxRange();
            seekToSeekBar(value, stand, maxRange);
            setRecoverEnable(checkFaceSkinChanged());
          } else if (checkedId == R.id.beauty_radio_face_shape) {
            mBeautyAdapter.setData(mShapeBeauty);
            recyclerView.setAdapter(mBeautyAdapter);
            FaceBeautyBean item = mShapeBeauty.get(mShapeIndex);
            double value = mDataFactory.getParamIntensity(item.getKey());
            double stand = mModelAttributeRange.get(item.getKey()).getStandV();
            double maxRange = mModelAttributeRange.get(item.getKey()).getMaxRange();
            seekToSeekBar(value, stand, maxRange);
            setRecoverEnable(checkFaceShapeChanged());
          } else if (checkedId == R.id.beauty_radio_filter) {
            recyclerView.setAdapter(mFiltersAdapter);
            recyclerView.scrollToPosition(mDataFactory.getCurrentFilterIndex());
            if (mDataFactory.getCurrentFilterIndex() == 0) {
              discreteSeekBar.setVisibility(View.INVISIBLE);
            } else {
              seekToSeekBar(
                  mFilters.get(mDataFactory.getCurrentFilterIndex()).getIntensity(), 0.0, 1.0);
            }
          } else if (checkedId == View.NO_ID) {
            mDataFactory.enableFaceBeauty(true);
          }
        });
  }
  // endregion
  // region  业务处理

  /**
   * 设置滚动条数值
   *
   * @param value Double 结果值
   * @param stand Double 标准值
   * @param range Double 范围区间
   */
  private void seekToSeekBar(double value, double stand, double range) {
    if (stand == 0.5) {
      discreteSeekBar.setMin(-50);
      discreteSeekBar.setMax(50);
      discreteSeekBar.setProgress((int) (value * 100 / range - 50));
    } else {
      discreteSeekBar.setMin(0);
      discreteSeekBar.setMax(100);
      discreteSeekBar.setProgress((int) (value * 100 / range));
    }
    discreteSeekBar.setVisibility(View.VISIBLE);
  }

  /** 更新单项是否为基准值显示 */
  private void updateBeautyItemUI(BaseViewHolder viewHolder, FaceBeautyBean bean) {
    double value = mDataFactory.getParamIntensity(bean.getKey());
    double stand = mModelAttributeRange.get(bean.getKey()).getStandV();
    if (viewHolder == null) {
      return;
    }
    if (DecimalUtils.doubleEquals(value, stand)) {
      viewHolder.setImageResource(R.id.iv_control, bean.getCloseRes());
    } else {
      viewHolder.setImageResource(R.id.iv_control, bean.getOpenRes());
    }
  }

  /**
   * 重置还原按钮状态
   *
   * @param enable Boolean
   */
  private void setRecoverEnable(Boolean enable) {
    if (enable) {
      recoverImageView.setAlpha(1f);
      recoverTextView.setAlpha(1f);
    } else {
      recoverImageView.setAlpha(0.6f);
      recoverTextView.setAlpha(0.6f);
    }
    recoverLayout.setEnabled(enable);
  }

  /**
   * 遍历美肤数据确认还原按钮是否可以点击
   *
   * @return Boolean
   */
  private boolean checkFaceSkinChanged() {
    FaceBeautyBean bean = mSkinBeauty.get(mSkinIndex);
    double value = mDataFactory.getParamIntensity(bean.getKey());
    double defaultV = mModelAttributeRange.get(bean.getKey()).getDefaultV();
    if (!DecimalUtils.doubleEquals(value, defaultV)) {
      return true;
    }
    for (FaceBeautyBean beautyBean : mSkinBeauty) {
      value = mDataFactory.getParamIntensity(beautyBean.getKey());
      defaultV = mModelAttributeRange.get(beautyBean.getKey()).getDefaultV();
      if (!DecimalUtils.doubleEquals(value, defaultV)) {
        return true;
      }
    }
    return false;
  }

  /**
   * 遍历美型数据确认还原按钮是否可以点击
   *
   * @return Boolean
   */
  private boolean checkFaceShapeChanged() {
    FaceBeautyBean bean = mShapeBeauty.get(mShapeIndex);
    double value = mDataFactory.getParamIntensity(bean.getKey());
    double defaultV = mModelAttributeRange.get(bean.getKey()).getDefaultV();
    if (!DecimalUtils.doubleEquals(value, defaultV)) {
      return true;
    }
    for (FaceBeautyBean beautyBean : mShapeBeauty) {
      value = mDataFactory.getParamIntensity(beautyBean.getKey());
      defaultV = mModelAttributeRange.get(beautyBean.getKey()).getDefaultV();
      if (!DecimalUtils.doubleEquals(value, defaultV)) {
        return true;
      }
    }
    return false;
  }

  /** 还原 美型、美肤数据 */
  private void recoverData() {
    if (checkGroup.getCheckedCheckBoxId() == R.id.beauty_radio_skin_beauty) {
      recoverData(mSkinBeauty, mSkinIndex);
    } else if (checkGroup.getCheckedCheckBoxId() == R.id.beauty_radio_face_shape) {
      recoverData(mShapeBeauty, mShapeIndex);
    }
  }

  /**
   * 重置数据
   *
   * @param beautyBeans
   * @param currentIndex
   */
  private void recoverData(ArrayList<FaceBeautyBean> beautyBeans, int currentIndex) {
    for (FaceBeautyBean bean : beautyBeans) {
      double intensity = mModelAttributeRange.get(bean.getKey()).getDefaultV();
      mDataFactory.updateParamIntensity(bean.getKey(), intensity);
    }
    FaceBeautyBean data = beautyBeans.get(currentIndex);
    double value = mDataFactory.getParamIntensity(data.getKey());
    double stand = mModelAttributeRange.get(data.getKey()).getStandV();
    double maxRange = mModelAttributeRange.get(data.getKey()).getMaxRange();
    seekToSeekBar(value, stand, maxRange);
    mBeautyAdapter.notifyDataSetChanged();
    setRecoverEnable(false);
  }

  public void checkSkinBeautyTab() {
    checkGroup.check(currentTab);
  }
}
